import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_frontend/utils/app_manager.dart';
import 'package:web_socket_channel/io.dart';

enum WebSocketState { connectError, connected, disconnect, unknown }

class WebSocketManager {
  static final WebSocketManager _instance = WebSocketManager._internal();

  factory WebSocketManager() => _instance;

  static WebSocketManager get sharedInstance => _instance;

  IOWebSocketChannel? _socketChannel;

  late String _url;

  // 心跳定时器
  Timer? _timer;

  // WebSocket连接状态
  WebSocketState _socketState = WebSocketState.unknown;

  WebSocketManager._internal();

  /// 连接服务器
  void connect(String url) {
    if (_socketChannel == null) {
      AppManager.sharedInstance.token.then((String? token) {
        if (token != null) {
          _url = url;
          Map<String, dynamic> headers = {'Sec-WebSocket-Protocol': 'JWT, ' + token};
          _socketChannel ??= IOWebSocketChannel.connect(_url, headers: headers);
          _socketChannel?.stream.listen((event) {
            debugPrint('websocket收到数据:$event');
            _socketState = WebSocketState.connected;
            if (event is String) {}
          }, onError: (error) {
            debugPrint('websocket连接失败$error');
            _socketState = WebSocketState.connectError;
          }, onDone: () {
            debugPrint('websocket连接断开');
            _socketState = WebSocketState.disconnect;
          });
          _heartPing();
          _timer ??= Timer.periodic(const Duration(seconds: 30), (timer) {
            _socketState == WebSocketState.connected ? _heartPing() : _reconnect(_url);
          });
        }
      });
    } else {
      if (_url != url) _reconnect(url);
    }
  }

  /// 心跳监测
  void _heartPing() {
    sendMessage({'cmd': 'ping'});
  }

  /// 发送消息
  void sendMessage(Map<String, dynamic> mapMessage) {
    _socketChannel?.sink.add(json.encode(mapMessage));
  }

  /// 断开连接
  void disconnect() {
    _socketChannel?.sink.close();
    _socketChannel = null;
    if (_timer != null) {
      _timer?.cancel();
      _timer = null;
    }
  }

  /// 重新连接
  void _reconnect(String url) {
    disconnect();
    connect(url);
  }
}
